/**   
 * Copyright 2011 COMERE Harold
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package etrl.core;

import etrl.vecmath.Quat4f;
import etrl.vecmath.Vector3f;
import etrl.vecmath.Vector4f;

/**
 * \class Transform
 * \brief Specialized node to apply a transformation on its childwood.
 * @author harold
 *
 */
public class Transform extends Group 
{
	/**
	 * Transformation data of the node
	 */
	private TransformData _transformData;
	
	/**
	 * \brief Initializes an identity transform.
	 */
	public Transform()
	{
		_transformData = new TransformData();
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void accept(NodeVisitor nodeVisitor)
	{
		nodeVisitor.visit(this);
	}
	
	/**
	 * \brief Get the transform data.
	 * @return Transform data.
	 */
	public TransformData getData()
	{
		return _transformData;
	}

	/**
	 * \brief Applies a rotation
	 * @param[in] rotationAxis rotation axis
	 * @param[in] rotationAngle rotation angle
	 * @param[in] local true : the rotation axis is defined in local space, false : in world space
	 */
	public void rotate(Vector3f rotationAxis, float rotationAngle, boolean local)
	{
		_transformData.applyRotation(rotationAxis, rotationAngle, local);
	}

	/**
	 * \brief Sets a new position
	 * @param[in] newPosition new position to set
	 */
	public void setPosition(Vector3f newPosition)
	{
		_transformData.setPosition(newPosition);
	}

	/**
	 * \brief Sets a new orientation as quaternion
	 * @param[in] newOrientation orientation to set
	 */
	public void setOrientation(Quat4f newOrientation)
	{
		_transformData.setOrientation(newOrientation);
	}
	
	/**
	 * \brief Applies a new uniform scale
	 * @param[in] uniformScale new uniform scale to apply
	 */
	public void setUniformScale(float uniformScale)
	{
		_transformData.setUniformScale(uniformScale);
	}
	
	/**
	 * \brief Applies a new scale
	 * @param[in] scale scale to apply
	 */
	public void setScale(final Vector3f scale)
	{
		_transformData.setScale(scale);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public BoundingSphere computeBoundingSphere()
	{
		// Get a new bounding sphere from Group function call
		BoundingSphere bsphere = super.computeBoundingSphere();

		// And apply transform on the center
		Vector4f center = bsphere.getCenter();
		_transformData.toMat4().transform(center);
		
		// The radius must be scaled according to the transform scale.
		// If the scale is uniform it is really simple
		float radius = bsphere.getRadius();
		Vector3f scale = _transformData.getScale();
		if(scale.x == scale.y && scale.y == scale.z)
		{
			radius *= scale.x;
		}
		else 
		{
			//System.out.println("GRMPPHHH");
			// else the scale is not uniform
			// TODO : find a way to rescale the radius correctly
		}

		bsphere.setCenter(center);
		bsphere.setRadius(radius);
		
		return bsphere;
	}
}
